#include "Tester.h"
using namespace std;
extern pthread_cond_t doneCond; 
extern pthread_mutex_t doneMutex; 
Tester::Tester()
{
    position.clear();
}


bool IsErrorRspInfo(CThostFtdcRspInfoField *pRspInfo)
{
    bool bResult = ((pRspInfo) && (pRspInfo->ErrorID != 0));
    if (bResult)
    {
        cerr << ">>> ErrorID=" << pRspInfo->ErrorID<<endl;// << ", ErrorMsg=" << pRspInfo->ErrorMsg << endl;
    }
    return bResult;
}

void Tester:: OnFrontDisconnected(int nReason)
{
    cerr << ">>> MdFrontDisconnected Reason = " << nReason << endl;
}

void Tester::OnHeartBeatWarning(int nTimeLapse)
{
    cerr << ">>> TradeHeartBeatWarning nTimerLapse = " << nTimeLapse << endl;
}

void Tester::OnFrontConnected()
{
    pthread_mutex_lock(&doneMutex);     
    pthread_cond_signal(&doneCond); 
    pthread_mutex_unlock (&doneMutex); 
}

void Tester::OnRspAuthenticate(CThostFtdcRspAuthenticateField *pRspAuthenticateField,CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }

}

void Tester::OnRspQryInstrument(CThostFtdcInstrumentField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if(Rtn->ExpireDate[0]!=0 &&
//		strcmp(Rtn->ExpireDate,"20370101") < 0 &&
		Rtn->IsTrading)
	{
		{
			cerr<<Rtn->InstrumentID<<"\t"<<Rtn->ExchangeID<<"\t"<<Rtn->ExpireDate<<"\t"<<Rtn->UnderlyingInstrID<<"\t"<<Rtn->StrikePrice<<"\t"<<Rtn->OptionsType<<endl;
			//instruments[Rtn->InstrumentID]= info.str();
		}
//		else
//			info<<Rtn->ExchangeID<<"\t"<<Rtn->ExpireDate<<"\t"<<Rtn->OptionsType<<"\t"<<Rtn->StrikePrice;
	}
	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }

}

void Tester::OnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) 
{
cerr<< Rtn->InstrumentID<<"\n"
<<"LongMarginRatioByVolume\t"<<Rtn->LongMarginRatioByVolume<<"\n"
<<"LongMarginRatioByMoney\t"<<Rtn->LongMarginRatioByMoney<<"\n";
	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }

};

void Tester::OnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
cerr<< Rtn->InstrumentID<<"\n"
	<< "OpenRatioByMoney\t"	<< Rtn->OpenRatioByMoney<<"\n"
    << "OpenRatioByVolume\t"    << Rtn->OpenRatioByVolume<<"\n"
    << "CloseRatioByMoney\t"    << Rtn->CloseRatioByMoney<<"\n"
    << "CloseRatioByVolume\t"    << Rtn->CloseRatioByVolume<<"\n"
    << "CloseTodayRatioByMoney\t" << Rtn->CloseTodayRatioByMoney<<"\n"
    << "CloseTodayRatioByVolume\t" << Rtn->CloseTodayRatioByVolume<<endl;

	if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex);
        pthread_cond_signal(&doneCond);
        pthread_mutex_unlock (&doneMutex);
    }


}

void Tester::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
                               CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 

    }
}


void Tester::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    pthread_mutex_lock(&doneMutex); 
    pthread_cond_signal(&doneCond); 
    pthread_mutex_unlock (&doneMutex); 

}



void Tester::OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if(Rtn)
    {
        if(Rtn->Volume!=0)
        {
            string instru=Rtn->InstrumentID;
            int v=Rtn->Volume * (Rtn->Direction==THOST_FTDC_D_Buy?1:-1);
            double price=Rtn->OpenPrice;
			fprintf(stderr,"%s %d %s %s %f\n",Rtn->InstrumentID,v, Rtn->OpenDate, Rtn->TradingDay, Rtn->OpenPrice);
                       
        }
    }
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 
    }
}

void Tester::OnRspQryOrder(CThostFtdcOrderField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    if (Rtn)
    {
        fprintf(stderr,"id:%3s %s%s %s %d %d %.0f %c\n",Rtn->OrderRef,(Rtn->Direction=='0'?" Buy":"Sell"),(strcmp(Rtn->CombOffsetFlag,"0")==0?" Open":"Close"),
		Rtn->InstrumentID,Rtn->VolumeTotal,Rtn->VolumeTraded,Rtn->LimitPrice,Rtn->OrderStatus);
        if(Rtn->OrderStatus==THOST_FTDC_OST_PartTradedQueueing || Rtn->OrderStatus==THOST_FTDC_OST_NoTradeQueueing)
        {          
            stringstream k,v;            
            char* OrderSysID=Rtn->OrderSysID;
            k<<Rtn->ExchangeID<<"|"<<OrderSysID;
            v<<(Rtn->Direction=='0'?"Buy":"Sell")<<(strcmp(Rtn->CombOffsetFlag,"0")==0?"Open":"Close")<<" "<<Rtn->InstrumentID<<" "<<Rtn->VolumeTotal<<"@"<<Rtn->LimitPrice;
            order[k.str()]=v.str();           
            
        }
    }
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 
    }
}


void Tester::OnRtnOrder(CThostFtdcOrderField *Rtn)
{
    if(Rtn)
    {
        if(Rtn->OrderStatus==THOST_FTDC_OST_Unknown)
            return;

	fprintf(stderr,"id:%s %s%s %s %f %d %d %c\n",Rtn->OrderRef,(Rtn->Direction==THOST_FTDC_D_Buy?"Buy":"Sell"),(Rtn->CombOffsetFlag[0]==THOST_FTDC_OF_Open?"Open ":"Close"),Rtn->InstrumentID, Rtn->LimitPrice, Rtn->VolumeTotal, Rtn->VolumeTraded, Rtn->OrderStatus);

        stringstream k;            
        char* OrderSysID=Rtn->OrderSysID;
        k<<Rtn->ExchangeID<<"|"<<OrderSysID;
        if(Rtn->OrderStatus==THOST_FTDC_OST_PartTradedQueueing || Rtn->OrderStatus==THOST_FTDC_OST_NoTradeQueueing)
        {             
            stringstream v;     
            v<<(Rtn->Direction=='0'?"Buy":"Sell")<<(strcmp(Rtn->CombOffsetFlag,"0")==0?"Open":"Close")<<" "<<Rtn->InstrumentID<<" "<<Rtn->VolumeTotal<<"@"<<Rtn->LimitPrice;
            order[k.str()]=v.str();
        //    cerr<<k.str()<<"\t"<<Rtn->OrderStatus<<"after"<<endl;
        }
        else if(order.find(k.str())!=order.end())
        {
            
            order.erase(k.str());
            
        }
         
        
    }
    

}

void Tester::OnRtnTrade(CThostFtdcTradeField *Rtn)
{

    cerr << Rtn->ExchangeID<<" "<<Rtn->OrderSysID<<" "<<Rtn->OrderRef<<" " <<Rtn->TradeTime<<"\t"<<
         (Rtn->Direction==THOST_FTDC_D_Buy?"Buy":"Sell")<<(Rtn->OffsetFlag==THOST_FTDC_OF_Open?"Open ":"Close")<<"\t"<<
         Rtn->InstrumentID<<"\t"<<
         Rtn->Volume<<" @ "<<Rtn->Price<<"\n";

    string instru=Rtn->InstrumentID;
    int v=Rtn->Volume * (Rtn->Direction==THOST_FTDC_D_Buy?1:-1);
    double price=Rtn->Price;
}

void Tester::OnRspQryTradingAccount(CThostFtdcTradingAccountField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    cerr<<setiosflags(ios::fixed)<<setprecision(2)
    << "\n=== Trading Account ==="
    <<"\nCurrMargin:\t"     <<Rtn->CurrMargin
    <<"\nCommission:\t"     <<Rtn->Commission
    <<"\nPositionProfit:\t" <<Rtn->PositionProfit
    <<"\nCloseProfit:\t"    <<Rtn->CloseProfit
    <<"\nAvailable:\t"      <<Rtn->Available
    <<"\nWithdrawQuota:\t"  <<Rtn->WithdrawQuota
    <<"\nBalance:\t"        <<Rtn->Balance
    <<endl;
    //totalAsset+=Rtn->Balance;
    if (bIsLast && !IsErrorRspInfo(pRspInfo))
    {
        pthread_mutex_lock(&doneMutex); 
        pthread_cond_signal(&doneCond); 
        pthread_mutex_unlock (&doneMutex); 
    }
}

void Tester::OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    cerr << ">>> OnRspOrderInsert" << endl;
    IsErrorRspInfo(pRspInfo);
}

void Tester::OnRspOrderAction(CThostFtdcInputOrderActionField *Rtn, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{

    cerr << ">>> OnRspOrderAction"<< endl;
    IsErrorRspInfo(pRspInfo);
}


void Tester::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
    cerr << ">>> OnRspError"<< endl;
    IsErrorRspInfo(pRspInfo);
}

